home *** CD-ROM | disk | FTP | other *** search
- Path: pegasus.montclair.edu!harmon
- From: harmon@pegasus.montclair.edu (Derek Harmon)
- Newsgroups: comp.lang.c
- Subject: Re: RETURN ();
- Date: 8 Feb 1996 20:31:47 -0500
- Organization: Montclair State University
- Message-ID: <harmon.823829370@pegasus.montclair.edu>
- References: <DMFxxq.7M7@emi.net>
- NNTP-Posting-Host: pegasus.montclair.edu
- X-Newsreader: NN version 6.5.0 #68 (NOV)
-
- ** Quoting a message by <samstar@emi.net> dated <08-Feb-1996>:
-
- > Is there a way to return muliple values to main from a seperate function ?
-
- Yes, but it won't be as straightforward as this:
-
- > return(x,y,z);
-
- Ready? :> Let's start with a little background,
-
- If you declare a function as returning an int ...
- ... C expects return() with an expression evaluating to an int
- (of course, that could be as simple as an int value or variable).
-
- The caller will receive that int if it is using the function as
- an part of an expression or assignment:
-
- : val_returned = func(x,y,z);
- : if ((val_returned = func(x,y,z+1)) != 0) { ...
-
- By using a simple type like int, however, you are limited to returning
- only one element of data. Unfortunately, C places limitations on the
- return of complex data types, but there are ways around this.
-
- Alternatives,
-
- : long int func(short int a, short int b, short int c)
- : {
- : long int temp;
- :
- : temp = max(a,b);
- : temp |= max(a,c) << 8;
- : temp |= max(b,c) << 16;
- :
- : return( temp );
- : }
-
- In this first example, which takes 3 bytes, compares all combinations
- determining the maximum of each, and then returns the 3 results of the
- these comparisons by masking the result into successively higher bytes
- of a long integer (usually 4-bytes). In effect, this function returns
- the max(a,b), max(a,c), and max(b,c). It has the drawback of requiring
- the caller to "unstuff" the returned long value.
-
- Many times we create structures and arrays in C, and are limited by
- the restrictions of C function parameters and return types. However,
- one of the most versatile, and often most complicated to the novice,
- data types is a simple type -- the pointer.
-
- So, if it is possible to return a pointer to a more complex data type,
- its not too difficult to reference it outside of the function. Here is
- an example in which the function reserves its own data space (note that
- it must be declared static, such that the data persists after the function
- concludes) as an array with enough elements to represent all of its return
- values.
-
- : float *func(float x0, float x, float y0, float y, float z0, float z)
- : {
- : static float delta[3];
- :
- : delta[0] = x0 - x;
- : delta[1] = y0 - y;
- : delta[2] = z0 - z;
- :
- : return( delta );
- : }
-
- This function returns a pointer to a float (real number). We are depending
- here upon an array reserved within func() to serve as the location for the
- values calculated by that function. We also rely upon delta, the name of an
- array, sans square brackets (delta[1] would be a float), to devolve into a
- pointer to the first element of delta (that would be delta[0]), when it
- is returned. Remember, this function is declared as a function returning
- a pointer to an float.. therefore return() must be given an expression
- that ends up as a pointer to an float.
-
- The benefits of this are that the parent program can access the multiple
- ints resulting from the processing of func(), as follows:
-
- : /* in another piece of code, in some function far, far away */
- : float *p;
- : float dx, dy, dz;
- :
- : p = func(17.0, 17.014, -5.5, -4.99734, 2.25, 2.252);
-
- Then displayed as:
-
- : dx = p[0];
- : dy = p[1];
- : dz = p[2];
- : printf("dx= %f, dy= %f, dz= %f", dx, dy, dz);
-
- Here the square brackets have been applied to the pointer, in effect,
- treating it as an array of floats. In this case, it is safe to do so
- because we know that there are 3 valid elements (held in the statically
- maintained delta[], in func() ). It is equivalent to using pointer
- arithmetic, and you may be more comfortable doing the following:
-
- : char v;
- :
- : v = 'x'
- : while (v <= 'z') {
- : printf("d%c= %f, ", v, *p);
- : p++;
- : }
-
- Maybe not everyone is comfortable with using chars as loop control
- variables, but that was only convenient to make the output identical
- to the last snippet. If you are only displaying, it doesn't matter
- if you lose the pointer's place, you can always back-up! :) The data
- is elsewhere.
-
- But there is a MAJOR caveat to go along with this seemingly more
- feasible solution to your troubles; be careful about your boundaries.
- Think of the havoc that could be wrought if we referenced p[7]. The
- static array only had 3 elements, not eight. p[7] is an address out
- in never-never land (20 bytes, or 5 * sizeof(float) past the end of
- the array)!
-
- In the example, it was clear that there were 3 variables, x, y, and
- z. If you were printing the answers, its difficult for you to come up
- with a letter after z and accidentally reference p[3]. :) But that is
- where pointers will get you if you don't use them with care. The
- approach of using an array to return multiple values from a function
- rests upon the assumption that the other functions have knowledge of
- how many values are to be returned (admittedly, bad design dogma).
-
- For a final illustration, I will suggest a protocol that would hopefully
- prevent this. Instead of knowing, func() returns 3 values, all outside
- functions need to be aware of is that func() returns a pointer to the
- first value of an answer, many more may follow in sequence, but they will
- be terminated by some arbitrary value not in the solution set (we will take
- this to be zero). This func() takes a number n, and returns a pointer to n,
- followed by the n - 1 numbers less than n, ending conveniently enough at 0. :)
-
- : int *func(int n)
- : {
- : int *head;
- : int *pt;
- :
- : if ((head = pt = (int *)malloc( (n + 1) * sizeof(int) )) == NULL) {
- : fputs( "Out of memory.\n", stderr);
- : exit( 1 );
- : }
- : while (n >= 0) {
- : *pt = n;
- : pt++;
- : n--;
- : }
- :
- : return( head );
- : }
-
- I hope some of these examples can be of help to you.
-
- -- Stone
- --
- [ SSS TTT OOO N N EEE ] Derek Harmon (a.k.a. Stonelight)
- [ S_ T O O NN N E_ ] E-Mail: harmon@pegasus.montclair.edu
- [ S T O O N NN E ] Computer Science Undergrad at
- [ SSS T OOO N N EEE ] Montclair State University, NJ
- (My views are entirely my own, nobody else is this creative :)
-
-
-